using System;
using System.Collections.Generic;

namespace TelerikMvcGridCustomBindingHelper.Mapper
{
    public static class GridModelMapper
    {
        static GridModelMapper()
        {
            Configuration = new FluentMapperConfiguration();
        }

        public static IFluentMapperConfiguration Configuration { get; private set; }

        internal static FluentMapperConfiguration ConfigurationObject { get { return (FluentMapperConfiguration)Configuration; } }

        /// <summary>
        /// This technique is for special cases where AutoMapper can not provide the mapped property, 
        /// for example if you are using CustomTypeConverters or something similar.
        /// Do not forget to map each entity property needed for the SQL query.
        /// </summary>
        /// <typeparam name="TEntity">Entity type</typeparam>
        /// <typeparam name="TViewModel">ViewModel type</typeparam>
        /// <returns>ExpressionMapping to map the properties of an entity with a ViewModel</returns>
        public static IMappingExpression<TEntity, TViewModel> CreateMap<TEntity, TViewModel>()
        {
            return GridModelMapperBase<TEntity, TViewModel>.CreateMap();
        }
        
        /// <summary>
        /// Clears all mappings and configurations
        /// </summary>
        public static void Reset()
        {
            Configuration = new FluentMapperConfiguration();
        }

        internal static List<GridPropertyInfo> GetPropertyMaps(Type entityType, Type viewModelType)
        {
            return GridModelMapperBase<object, object>.GetPropertyMaps(entityType, viewModelType);
        }

        internal static List<GridPropertyInfo> GetPropertyMaps()
        {
            return GridModelMapperBase<object, object>.GetPropertyMaps();
        }

        internal static GridPropertyInfo GetPropertyMap<TEntity, TViewModel>(string viewModelPropertyName)
        {
            return GridModelMapperBase<TEntity, TViewModel>.GetPropertyMap(viewModelPropertyName);
        }

        internal static IEnumerable<TDestination> Map<TSource, TDestination>(IEnumerable<TSource> sources)
        {
            AssertMappings<TSource, TDestination>();
            return AutoMapper.Mapper.Map<IEnumerable<TDestination>>(sources);
        }

        internal static void AssertMappings<TSource, TDestination>()
        {
            if (typeof(TSource).IsAssignableFrom(typeof(TDestination)))
            {
                return;
            }

            var typeMap = AutoMapper.Mapper.FindTypeMapFor<TSource, TDestination>();

            if (ConfigurationObject.ShouldCreateSimpleMappingsAsNeeded && typeMap == null)
            {
                AutoMapper.Mapper.CreateMap<TSource, TDestination>();
            }

            Guard.IsMapped<TSource, TDestination>();
        }
    }
}